#include "Camera.h"

/*The default Constructor*/
Camera::Camera(void)
{
	/*Make our Matricies all Identities so they have no values or something random that can affect the start of the game*/
	D3DXMatrixIdentity(&m_ViewMat);
	D3DXMatrixIdentity(&m_ProjMat);
	D3DXMatrixIdentity(&m_ViewProjMat);

	/*Clear out all of our vectors(2D, 3D, and Quaternions) so that they don't start out with random values*/
	ZeroMemory(&m_RightVec, sizeof(D3DXVECTOR3));
	ZeroMemory(&m_EyePos, sizeof(D3DXVECTOR3));
	ZeroMemory(&m_LookAt, sizeof(D3DXVECTOR3));
	ZeroMemory(&m_UpVec, sizeof(D3DXVECTOR3));

	/*Clear out all of our normal data types to the default value so that they don't start out with random values*/
	m_CameraSpeed = 15.0f;
	m_CameraPitch = 0;
	m_CameraYAngle = 0;
}

/*The default Destructor*/
Camera::~Camera(void)
{
}

/*The function to create and initialize all of the variables within*/
void Camera::Initialize(int height, int width, Input* in)
{
	/*Set the height to the sent in height*/
	m_Height = height;

	/*Set the width to the sent in width*/
	m_Width = width;

	/*Set the input pointer to the sent in input pointer*/
	m_Input = in;

	/*Set the position of the camera to (0,0,0)*/
	m_EyePos = D3DXVECTOR3(0,0,0);

	/*Set the camera to look down the Z axis*/
	m_LookAt = D3DXVECTOR3(0,0,1);

	/*Make the positive Y axis the beginning up vector*/
	m_UpVec = D3DXVECTOR3(0,1,0);

	/*Make the positive X axis the beginning right vector*/
	m_RightVec = D3DXVECTOR3(1,0,0);

	/*Create the View Matrix*/
	createViewMat();

	/*Create the Projection Matrix*/
	createProjMat();

	/*Create the viewproj matrix*/
	m_ViewProjMat = m_ViewMat * m_ProjMat;
}

/*The function that will create the View Matrix*/
void Camera::createViewMat()
{
	/*Make sure that the Look at vector is of unit length*/
	D3DXVec3Normalize(&m_LookAt, &m_LookAt);

	/*The up vector is the cross product of the look and the right vectors*/
	D3DXVec3Cross(&m_UpVec, &m_LookAt, &m_RightVec);

	/*Make sure that the Up vector is of unit length*/
	D3DXVec3Normalize(&m_UpVec, &m_UpVec);

	/*The right vector is the cross product of the look and the up vectors*/
	D3DXVec3Cross(&m_RightVec, &m_UpVec, &m_LookAt);

	/*Make sure that the Right vector is of unit length*/
	D3DXVec3Normalize(&m_RightVec, &m_RightVec);

	/*The x corresponds to the 3 element in the matrix for the view, its the dot of pos and right*/
	float x = -D3DXVec3Dot(&m_EyePos, &m_RightVec);

	/*The y corresponds to the 3 element in the matrix for the view, its the dot of pos and up*/
	float y = -D3DXVec3Dot(&m_EyePos, &m_UpVec);

	/*The z corresponds to the 3 element in the matrix for the view, its the dot of pos and look at*/
	float z = -D3DXVec3Dot(&m_EyePos, &m_LookAt);

	/*The first column is the right information*/
	m_ViewMat(0,0) = m_RightVec.x;
	m_ViewMat(1,0) = m_RightVec.y;
	m_ViewMat(2,0) = m_RightVec.z;
	m_ViewMat(3,0) = x;

	/*The second column is the up information*/
	m_ViewMat(0,1) = m_UpVec.x;
	m_ViewMat(1,1) = m_UpVec.y;
	m_ViewMat(2,1) = m_UpVec.z;
	m_ViewMat(3,1) = y;

	/*The third column is the look at information*/
	m_ViewMat(0,2) = m_LookAt.x;
	m_ViewMat(1,2) = m_LookAt.y;
	m_ViewMat(2,2) = m_LookAt.z;
	m_ViewMat(3,2) = z;

	/*The last column is just Identity*/
	m_ViewMat(0,3) = 0.0f;
	m_ViewMat(1,3) = 0.0f;
	m_ViewMat(2,3) = 0.0f;
	m_ViewMat(3,3) = 1.0f;
}

/*The function that will create the Projection Matrix*/
void Camera::createProjMat()
{
	/*Create the Projection matrix and set it for the projection State*/
	D3DXMatrixPerspectiveFovLH(&m_ProjMat,							//Output Matrix
		D3DXToRadian(65),					//Radian degree measure for field of view
		(float)m_Width/(float)m_Height,		//Aspect Ratio
		1.0f,								//Near plane
		1000.0f);							//Far Plane
}

/*The function returns the view matrix*/
D3DXMATRIX Camera::getView() 
{
	return m_ViewMat;
}

/*The function returns the Proj matrix*/
D3DXMATRIX Camera::getProj() 
{
	return m_ProjMat;
}

/*The function returns the viewProj matrix*/
D3DXMATRIX Camera::getViewProj() 
{
	return m_ViewProjMat;
}

/*The function returns the Right vector*/
D3DXVECTOR3 Camera::getRight()
{
	return m_RightVec;
}

/*The function returns the Up vector*/
D3DXVECTOR3 Camera::getUp()
{
	return m_UpVec;
}

/*The function returns the look vector*/
D3DXVECTOR3 Camera::getLook()
{
	return m_LookAt;
}

/*The function returns the position of the camera*/
D3DXVECTOR3 Camera::getPos() 
{
	return m_EyePos;
}

/*The function sets the position of the camera*/
void Camera::setPos(D3DXVECTOR3 pos)
{
	m_EyePos = pos;
}

/*The function sets the speed of the camera*/
void Camera::setSpeed(float speed)
{
	m_CameraSpeed = speed;
}

/*Update Everything for the Camera*/
void Camera::update(float dt)
{
	/*Vector to get the net direction the camera is travelling*/
	D3DXVECTOR3 dir(0.0f,0.0f,0.0f);

	/*Check to see if the A key is pressed*/
	if(m_Input->keyDown(DIK_A))
	{
		dir -= m_RightVec;
	}

	/*Check to see if the D key is pressed*/
	if(m_Input->keyDown(DIK_D))
	{
		dir += m_RightVec;
	}

	/*Check to see if the W key is pressed*/
	if(m_Input->keyDown(DIK_W))
	{
		dir += m_LookAt;
	}

	/*Check to see if the S key is pressed*/
	if(m_Input->keyDown(DIK_S))
	{
		dir -= m_LookAt;
	}

	/*Normalize the Direction*/
	D3DXVec3Normalize(&dir,&dir);

	/*Move along the direction at camera speed & dt*/
	m_EyePos += dir*m_CameraSpeed*dt;

	/*The angle to rotate the right vector*/
	m_CameraPitch = m_Input->mouseY() / 150.0f;

	/*The angle to rotate the entire world*/
	m_CameraYAngle = m_Input->mouseX() / 150.0f;

	/*Create the rotation matrix*/
	D3DXMATRIX rotation;

	/*Create the rotation axis with the right vector and the pitch*/
	D3DXMatrixRotationAxis(&rotation, &m_RightVec, m_CameraPitch);

	/*Rotate the look vector by the rotation matrix*/
	D3DXVec3TransformCoord(&m_LookAt, &m_LookAt, &rotation);

	/*Rotate the Up vector by the rotation matrix*/
	D3DXVec3TransformCoord(&m_UpVec, &m_UpVec, &rotation);

	/*Rotate the rotation's Y axis by the Y angle*/
	D3DXMatrixRotationY(&rotation, m_CameraYAngle);

	/*Rotate the Right vector by the rotation matrix*/
	D3DXVec3TransformCoord(&m_RightVec, &m_RightVec, &rotation);

	/*Rotate the up vector by the rotation matrix*/
	D3DXVec3TransformCoord(&m_UpVec, &m_UpVec, &rotation);

	/*Rotate the look vector by the rotation matrix*/
	D3DXVec3TransformCoord(&m_LookAt, &m_LookAt, &rotation);

	/*Rebuild the view Matrix*/
	createViewMat();

	/*Build the ViewProj matrix*/
	m_ViewProjMat = m_ViewMat * m_ProjMat;
}
